package org.sbbs.base.jpa.manager;

import java.io.Serializable;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;

import org.sbbs.base.jpa.dao.BaseRepo;
import org.sbbs.base.jpa.entity.BaseEntity;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.history.Revision;
import org.springframework.data.history.Revisions;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.repository.history.RevisionRepository;
import org.springframework.data.repository.query.FluentQuery;
import org.springframework.lang.Nullable;

/**
 * @param <T>
 * @param <ID>
 * @author jenkins
 */
public interface BaseManager<T extends BaseEntity, ID extends Serializable, R extends BaseRepo> {
    /*self*/
    public Page<Long> findAllIds(Pageable pageable);
   public T findById(ID id);
    /*jpa*/
    public void flush();

    public <S extends T> S saveAndFlush(S entity);

    public <S extends T> List<S> saveAllAndFlush(Iterable<S> entities);

    /**
     * @deprecated
     */
    @Deprecated
    public default void deleteInBatch(Iterable<T> entities) {
        this.deleteAllInBatch(entities);
    }

    public void deleteAllInBatch(Iterable<T> entities);

    public void deleteAllByIdInBatch(Iterable<ID> ids);

    public void deleteAllInBatch();

    /**
     * @deprecated
     */
    @Deprecated
    public T getOne(ID id);

    /**
     * @deprecated
     */
    @Deprecated
    public T getById(ID id);

    public T getReferenceById(ID id);

    public <S extends T> List<S> findAll(Example<S> example);

    public <S extends T> List<S> findAll(Example<S> example, Sort sort);
    /*crud*/


//    public Optional<T> findById(ID id);

    public boolean existsById(ID id);


    public long count();

    public void deleteById(ID id);

    public void delete(T entity);

    public void deleteAllById(Iterable<? extends ID> ids);

    public void deleteAll(Iterable<? extends T> entities);

    public void deleteAll();


    /*list crud*/
    public <S extends T> List<S> saveAll(Iterable<S> entities);

    public List<T> findAll();

    public List<T> findAllById(Iterable<ID> ids);


    /*page*/
    public List<T> findAll(Sort sort);

    public Page<T> findAll(Pageable pageable);

    /*specification*/
    public Optional<T> findOne(Specification<T> spec);

    public List<T> findAll(@Nullable Specification<T> spec);

    public Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable);

    public List<T> findAll(@Nullable Specification<T> spec, Sort sort);

    public long count(@Nullable Specification<T> spec);

    public boolean exists(Specification<T> spec);

    public long delete(@Nullable Specification<T> spec);

    public <S extends T, R> R findBy(Specification<T> spec, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction);

    /*example*/
    public <S extends T> Optional<S> findOne(Example<S> example);


    public <S extends T> Page<S> findAll(Example<S> example, Pageable pageable);

    public <S extends T> long count(Example<S> example);

    public <S extends T> boolean exists(Example<S> example);

    public <S extends T, R> R findBy(Example<S> example, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction);

    /*end*/


    public List<T> findAllById(List<ID> ids);


    public T save(T entity);

    public List<T> saveAll(List<T> entities);

    public boolean remove(T entity);

    public void removeAll(List<T> list);

    public boolean removeById(ID id);

    public void removeAllById(List<? extends ID> ids);

    public BaseRepo<T, ID> getRepo();

    public Optional<Revision<Long, T>> findLastChangeRevision(ID id);

    public Revisions<Long, T> findRevisions(ID id);

    public Page<Revision<Long, T>> findRevisions(ID id, Pageable pageable);

    public Optional<Revision<Long, T>> findRevision(ID id, Long revisionNumber);
}
 